package com.patternity.dotgraph;

import java.util.StringTokenizer;

/**
 * Helper functions to generate dot code for basic UML diagrams elements
 * 
 * @author cyrille martraire
 */
public class DotUmlHelper {

	protected static final String TAB = "\t";

	protected static final String NEW_LINE = "\n";

	private static final String OPEN_STEREOTYPE = "\\<" + "\\<";

	private static final String CLOSE_STEREOTYPE = "\\>" + "\\>";

	protected DotUmlHelper() {
	}

	public static String fontname(final String fontname) {
		return "fontname=\"" + fontname + "\"";
	}

	public static String fontsize(final int fontsize) {
		return "fontsize=" + fontsize;
	}

	public static String options(final String fontname, final int fontsize) {
		return fontname(fontname) + "," + fontsize(fontsize);
	}

	public static String options(final boolean isAbstract) {
		return fontname(isAbstract ? "Verdana-Italic" : "Verdana") + ", "
				+ fontsize(9);
	}

	public static String stereotype(final String str) {
		return OPEN_STEREOTYPE + str + CLOSE_STEREOTYPE;
	}

	public static String openGraph(final String title) {
		final StringBuffer sb = new StringBuffer();
		sb.append("# Class diagram ");
		sb.append(title);
		sb.append(NEW_LINE);
		sb.append("digraph G {");

		if (title != null) {
			sb.append(graphTitle(title));
		}
		sb.append(optionsEdge());
		sb.append(optionsNode());

		return sb.toString();
	}

	public static String closeGraph() {
		return "\n}\n";
	}

	public static String graphTitle(final String title) {
		final StringBuffer sb = new StringBuffer();
		sb.append(NEW_LINE);
		sb.append(TAB);
		sb.append("graph");
		sb.append(" ");
		sb.append("[");
		sb.append("labelloc=top,label=\"");
		sb.append(title);
		sb.append("\"");
		sb.append(",");
		sb.append(options("Verdana", 12));
		sb.append("]");
		sb.append(";");
		return sb.toString();
	}

	public static String optionsNode() {
		final StringBuffer sb = new StringBuffer();
		sb.append(NEW_LINE);
		sb.append(TAB);
		sb.append("node");
		sb.append(" ");
		sb.append("[");
		sb.append(options("Verdana", 9));

		sb.append(",");
		sb.append("shape=record");

		sb.append("]");
		sb.append(";");
		return sb.toString();
	}

	public static String optionsEdge() {
		final StringBuffer sb = new StringBuffer();
		sb.append(NEW_LINE);
		sb.append(TAB);
		sb.append("edge");
		sb.append(" ");
		sb.append("[");
		sb.append(options("Verdana", 9));

		sb.append(",");
		sb.append("labelfontname=\"");
		sb.append("Verdana");
		sb.append("\",labelfontsize=");
		sb.append(9);

		sb.append("]");
		sb.append(";");
		return sb.toString();
	}

	public static String edge(final String uniqueNameFrom,
			final String uniqueNameTo, final String comment,
			final String labels, final String edgeStyle) {
		if (uniqueNameFrom == null || uniqueNameTo == null) {
			return "";
		}
		final StringBuffer sb = new StringBuffer();
		sb.append(NEW_LINE);
		sb.append(TAB);
		sb.append("// ");
		sb.append(comment);

		sb.append(NEW_LINE);
		sb.append(TAB);
		sb.append(uniqueNameFrom);
		sb.append(" -> ");
		sb.append(uniqueNameTo);
		sb.append(" [");
		if (labels != null) {
			sb.append(labels);
			sb.append("  ");
			sb.append(", ");
		}
		sb.append(edgeStyle);
		sb.append("];");

		return sb.toString();
	}

	public static String line(final String[] cells, final String prefix,
			final String postfix) {
		if (cells == null || cells.length == 0) {
			return "";
		}
		final StringBuffer sb = new StringBuffer();
		for (int i = 0; i < cells.length; i++) {
			if (i > 0) {
				sb.append(prefix);
			}
			sb.append(cells[i]);
			sb.append(postfix);
		}
		return sb.toString();
	}

	public static String wrapText(final String text, final int length) {
		final StringBuffer sb = new StringBuffer();
		final StringTokenizer st = new StringTokenizer(text, " \t\n", true);
		int lineLength = 0;
		while (st.hasMoreElements()) {
			final String token = st.nextToken();
			if (lineLength > length) {
				lineLength = 0;
				sb.append("\\l");
			}
			sb.append(token);
			lineLength += token.length();
		}
		return sb.toString();
	}

	public static String node(final String uniqueName, final String label,
			final String options) {
		final StringBuffer sb = new StringBuffer();
		sb.append(NEW_LINE);
		sb.append(TAB);
		sb.append(uniqueName);
		sb.append(" ");
		sb.append("[");
		sb.append("label=\"");
		sb.append(label);
		sb.append("\"");
		if (options != null) {
			sb.append(", ");
			sb.append(options);
		}
		sb.append("]");
		return sb.toString();
	}

}
